package com.godliu.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;

import java.util.concurrent.TimeUnit;

/**
 * 认证的核心配置
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    ClientDetailsService detailsService;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //系统模式会拒绝一起token请求，所以要重载配置
        security.tokenKeyAccess("permitAll()") //放开所有获取token请求
            .checkTokenAccess("permitAll()") //检查token的请求也要放开
            .allowFormAuthenticationForClients();//支持客户端发来的校验请求
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //给第三方客户端的配置，记录哪些客户端可以从我这拿认证
        clients.inMemory().withClient("godliu") //设置客户端id
                .redirectUris("https://www.baidu.com") //设置回调地主，这个地址倒是附加授权码
                .autoApprove(false) //关闭自动通过，需要用户自己手动点击确认
                .scopes("all") //作用域 针对资源的操作权限 读  写
                .secret(bCryptPasswordEncoder.encode("helloworld")) //客户端认证密码
                .authorizedGrantTypes(
                        "authorization_code", //授权码模式
                        "password",//密码模式
                        "client_credentials",//客户端模式
                        "implicit",//简化模式
                        "refresh_token"//刷新token
                ) //token生成策略配置类型，有客户端模式、密码模式
                .resourceIds("r1","r2");//要访问的资源编号
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager) //先取到auth的管理配置
            .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET) //设置允许POST和GET方法
            .tokenServices(getTokenService()); //需要配置tokenService
    }

    /**
     * 设置token生成策略
     * @return
     */
    public AuthorizationServerTokenServices getTokenService(){
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(new InMemoryTokenStore());//TOKEN存储方式
        defaultTokenServices.setSupportRefreshToken(true);//支持刷新token
        defaultTokenServices.setClientDetailsService(detailsService);
        defaultTokenServices.setAccessTokenValiditySeconds((int) TimeUnit.SECONDS.toSeconds(3000L));
        return defaultTokenServices;
    }

}
